package lxs.swift.collector.tuple;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

public class TupleCreator {
    private static String codec(String packagePath, int num) {
        String className = "Tuple" + (num);
        String empty = "    ";
        String[] types = new String[num];
        String[] names = new String[num];
        String[] equalList = new String[num];
        StringBuilder fields = new StringBuilder();
        StringBuilder args = new StringBuilder();
        StringBuilder sets = new StringBuilder();
        StringBuilder signs = new StringBuilder();
        StringBuilder ts = new StringBuilder();

        for (int i = 0; i < num; i++) {
            types[i] = ("T" + (i + 1));
            names[i] = ("_" + (i + 1));
            signs.append("?,");
            ts.append("T,");
            equalList[i] = ("Objects.equals(" + names[i] + ", other." + names[i] + ")");
            fields.append(empty).append("public ").append(types[i]).append(" ").append(names[i]).append(";\n");
            args.append("final ").append(types[i]).append(" ").append(names[i]).append(",");
            sets.append(empty).append(empty).append("this.").append(names[i]).append(" = ").append(names[i]).append(";\n");

        }
        {
            signs.deleteCharAt(signs.length() - 1);
            ts.deleteCharAt(ts.length() - 1);
            args.deleteCharAt(args.length() - 1);
        }
        String equals = String.join(" && ", equalList);
        String TYPES = String.join(",", types);
        String NAMES = String.join(",", names);

        StringBuilder sb = new StringBuilder();
        sb.append("package ").append(packagePath).append(";\n");
        sb.append("\n");
        sb.append("import java.util.Objects;\n\n");
        sb.append("public class ").append(className).append("<").append(TYPES).append("> implements Tuple {\n");
        sb.append(fields);
        sb.append("\n");
        // private Tuple2(final T1 _1, final T2 _2)

        {
            sb.append(empty).append("protected ").append(className).append("() {\n");
            sb.append(empty).append("}\n");
            sb.append("\n");
        }

        {
            sb.append(empty).append("protected ").append(className).append("(").append(args).append("){\n");
            sb.append(sets);
            sb.append(empty).append("}\n");
            sb.append("\n");
        }
        //public Object[] toArray()
        sb.append(empty).append("@Override\n")
                .append(empty).append("public Object[] toArray() {\n")
                .append(empty).append(empty).append("return new Object[]{").append(NAMES).append("};\n")
                .append(empty).append("}\n\n");
        sb.append(empty).append("@Override\n")
                .append(empty).append("public boolean equals(Object o) {\n")
                .append(empty).append(empty).append("if (o == this) return true;\n")
                .append(empty).append(empty).append("if (o == null || getClass() != o.getClass()) return false;\n")
                .append(empty).append(empty).append(className).append("<").append(signs).append("> other = (").append(className).append("<").append(signs).append(">) o;\n")
                .append(empty).append(empty).append("return ").append(equals).append(";\n")
                .append(empty).append("}\n\n");
        sb.append(empty).append("@Override\n")
                .append(empty).append("public int hashCode() {\n")
                .append(empty).append(empty).append("return Objects.hash(").append(NAMES).append(");\n")
                .append(empty).append("}\n\n");
        sb.append(empty).append("@Override\n")
                .append(empty).append("public String toString() {\n")
                .append(empty).append(empty).append("return \"Tuple(\" + ").append(String.join(" + \", \" + ", names)).append("+')';\n")
                .append(empty).append("}\n\n");

        sb.append("}\n");


        {
            //静态函数 of
            StringBuilder sbb = new StringBuilder();
            sbb.append("static <").append(TYPES).append("> ").append(className).append("<").append(TYPES).append("> of(").append(args).append(") {\n");
            sbb.append(empty).append("return new ").append(className).append("<>(").append(NAMES).append(");\n");
            sbb.append("}\n\n");
            System.out.println(sbb.toString().replace("final ", ""));
        }

        {
            //静态函数 from
            StringBuilder sbb = new StringBuilder();
            sbb.append("static <T>").append(className).append("<").append(ts).append("> from").append(num).append("(@NotNull Iterable<T> iterable) {\n");
            sbb.append(empty).append(className).append("<").append(ts).append("> empty = new ").append(className).append("<>();\n");
            sbb.append(empty).append("fill(empty, ").append(num).append(", iterable);\n");
            sbb.append(empty).append("return empty;\n");
            sbb.append("}\n\n");
            System.out.println(sbb.toString().replace("final ", ""));
        }
        return sb.toString();
    }

    private static void writeCode(String path, String packagePath, int num) throws IOException {
        String className = "Tuple" + (num) + ".java";
        path += className;
        String codec = codec(packagePath, num);
        Path filePath = Paths.get(path);
        if (!Files.exists(filePath)) {
            Files.createFile(filePath);
        }
        Files.write(filePath, codec.getBytes(StandardCharsets.UTF_8));
    }

//    public static void main(String[] args) throws IOException {
//        for (int i = 2; i <= 9; i++) {
//            writeCode("D:\\project\\swifter\\src\\main\\java\\lxs\\swift\\collector\\tuple\\",
//                    "lxs.swift.collector.tuple", i);
//
//        }
//
//    }
}
